package ru.paswd.marketprice.rest.app.services;

import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import ru.paswd.marketprice.distance.calculator.DistanceCalculator;
import ru.paswd.marketprice.rest.api.dto.PriceWithShop;
import ru.paswd.marketprice.rest.api.exceptions.ProductNotFoundException;
import ru.paswd.marketprice.rest.app.mappers.PriceMapper;
import ru.paswd.marketprice.rest.app.repositories.PricesRepository;
import ru.paswd.marketprice.rest.app.repositories.ProductsRepository;

import java.util.Comparator;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class PriceService {

    private final PricesRepository pricesRepository;
    private final ProductsRepository productsRepository;
    private final PriceMapper priceMapper;
    private final DistanceCalculator distanceCalculator;

    public List<PriceWithShop> getPriceList(
            UUID productId, Integer radiusMeters, Double lat, Double lng, boolean sortByPrice) {

        ru.paswd.marketprice.rest.app.entity.Product product =
                productsRepository.findById(productId)
                        .orElseThrow(ProductNotFoundException::new);

        List<ru.paswd.marketprice.rest.app.entity.Price> prices =
                pricesRepository.findAllByProduct(product);

        return prices.stream()
                .filter(i -> radiusMeters == null || distanceCalculator.getDistance(
                        lat, lng, i.getShop().getLat(), i.getShop().getLng()) <= radiusMeters)
                .map(p -> {
                    PriceWithShop priceWithShop = priceMapper.toDto(p);
                    priceWithShop.setDistance(
                            distanceCalculator.getDistance(
                                    lat, lng, p.getShop().getLat(), p.getShop().getLng()));
                    return priceWithShop;
                })
                .sorted(sortByPrice
                        ? Comparator.comparingInt(PriceWithShop::getPrice)
                        : Comparator.comparingInt(PriceWithShop::getDistance))
                .collect(Collectors.toList());
    }
}
